#include "arbre_evaluation.h"
#include "struct.h"



/* Fonction d'affichage de l'arbre permettant un debug et le teste des boucles de parcours */
void affiche_feuille(feuille * f, abeille * ab, fleur ** fleurs, case_t grille[NB_COL][NB_LIGNES]){
		//printf("---Affiche feuille ---- \n");
		if(f->fonction != NULL) {
			//printf("TOTO");
			affiche_fonction(f->fonction, ab, fleurs, grille);
		} else if(f->variable != NULL) {
			affiche_variable(f->variable, ab, fleurs, grille);
		} else {
			printf("\nPOURQUOI\n");
			printf("%d", f->val);
		}
}

void affiche_fonction(fonction * f, abeille * ab, fleur ** fleurs, case_t grille[NB_COL][NB_LIGNES]){
		//printf("---Affiche fonction ---- \n");
	switch(f->type) {
		case FCT_GRILLE:
			// fonction grille(X,Y)
			printf("grille(");
			affiche_arbre(f->param1, ab, fleurs, grille);
			printf(", ");	
			affiche_arbre(f->param2, ab, fleurs, grille);
			printf(")");	
			break;
		case FCT_FLEUR:
			// fonction fleur(X,Y)
			printf("fleur(");
			affiche_arbre(f->param1, ab, fleurs, grille);
			printf(", ");	
			affiche_arbre(f->param2, ab, fleurs, grille);
			printf(")");	
			break;
		case FCT_ENNEMIE:
			// fonction ennemie(X,Y)
			printf("ennemie(");
			affiche_arbre(f->param1, ab, fleurs, grille);
			printf(", ");	
			affiche_arbre(f->param2, ab, fleurs, grille);
			printf(")");	
			break;
		case FCT_ESTLIBRE:
			// fonction estLibre(id)
			printf("estLibre(");
			affiche_arbre(f->param1, ab, fleurs, grille);
			printf(")");
			break;
		case FCT_NECTAR:
			// fonction nectar(id)
			printf("nectar(");
			affiche_arbre(f->param1, ab, fleurs, grille);
			printf(")");	
			break;
		case FCT_DISTANCE:
			// fonction distance(X1,Y1,X2,Y2)
			printf("distance(");
			affiche_arbre(f->param1, ab, fleurs, grille);
			printf(", ");	
			affiche_arbre(f->param2, ab, fleurs, grille);
			printf(", ");	
			affiche_arbre(f->param3, ab, fleurs, grille);
			printf(", ");	
			affiche_arbre(f->param4, ab, fleurs, grille);
			printf(")");	
			break;
	}
}

void affiche_variable(symbole * s, abeille * ab, fleur ** fleurs, case_t grille[NB_COL][NB_LIGNES]){
		//printf("---Affiche variable ---- \n");
	printf("%s",s->nom);
}

void affiche_arbre(arbre * arbre, abeille * ab, fleur ** fleurs, case_t grille[NB_COL][NB_LIGNES]){
	//printf("\nAFFICHE ARBRE\n");
	if(arbre->f != NULL){
		affiche_feuille(arbre->f, ab, fleurs, grille);
	} else {
		affiche_noeud(arbre->n, ab, fleurs, grille);
	}
}

void affiche_noeud(noeud * n, abeille * ab, fleur ** fleurs, case_t grille[NB_COL][NB_LIGNES]){
	//printf("---Affiche noeud ---- \n");
	affiche_arbre(n->fg, ab, fleurs, grille);
	switch (n->operateur){
		case OP_PLUS:
			printf(" + ");
			break;
		case OP_MOINS:
			printf(" - ");
			break;
		case OP_MULTI:
			printf(" * ");
			break;
		case OP_DIV:
			printf(" / ");
			break;
		case OP_MOD:
			printf(" %% ");
			break;
		case OP_SUP:
			printf(" > ");
			break;
		case OP_INF:
			printf(" < ");
			break;
		case OP_SUPEGAL:
			printf(" >= ");
			break;
		case OP_INFEGAL:
			printf(" <= ");
			break;
		case OP_EGALEGAL:
			printf(" == ");
			break;
		case OP_NONEGAL:
			printf(" != ");
			break;
		case OP_AND:
			printf(" && ");
			break;
		case OP_OR:
			printf(" || ");
			break;
	}
	affiche_arbre(n->fd, ab, fleurs, grille);
}

/* Fonction d'évaluation de l'arbre basées sur les fonctions d'affichages */

int evaluer_arbre(arbre * a, abeille * ab, fleur ** fleurs, case_t grille[NB_COL][NB_LIGNES]){
	
	if(a->n==NULL) {
		// feuille unique
		return evaluer_feuille(a->f, ab, fleurs, grille);	
	} else {
		// arbre
		return evaluer_noeud(a->n, ab ,fleurs, grille);	
	}
	
}

int evaluer_feuille(feuille * f, abeille * ab, fleur ** fleurs, case_t grille[NB_COL][NB_LIGNES]){
		if(f->fonction != NULL) {
			return evaluer_fonction(f->fonction,ab,fleurs,grille);
		} else if(f->variable != NULL) {
			return evaluer_variable(f->variable,ab,fleurs,grille);
		} else {
			return f->val;
		}
}

int evaluer_noeud(noeud * n, abeille * ab, fleur ** fleurs, case_t grille[NB_COL][NB_LIGNES]){
	int res_fg = evaluer_arbre(n->fg,ab,fleurs,grille);
	int res_fd = evaluer_arbre(n->fd,ab,fleurs,grille);
	switch (n->operateur){
		case OP_PLUS:
			return res_fg + res_fd;
			break;
		case OP_MOINS:
			return res_fg - res_fd;
			break;
		case OP_MULTI:
			return res_fg * res_fd;
			break;
		case OP_DIV:
			return res_fg / res_fd;
			break;
		case OP_MOD:
			return res_fg % res_fd;
			break;
		case OP_SUP:
			return res_fg > res_fd;
			break;
		case OP_INF:
			return res_fg < res_fd;
			break;
		case OP_SUPEGAL:
			return res_fg >= res_fd;
			break;
		case OP_INFEGAL:
			return res_fg <= res_fd;
			break;
		case OP_EGALEGAL:
			return res_fg == res_fd;
			break;
		case OP_NONEGAL:
			return res_fg != res_fd;
			break;
		case OP_AND:
			return res_fg && res_fd;
			break;
		case OP_OR:
			return res_fg || res_fd;
			break;
	}
}

int evaluer_fonction(fonction * f, abeille * ab, fleur ** fleurs, case_t grille[NB_COL][NB_LIGNES]){
	switch(f->type) {
		case FCT_GRILLE :
			// fonction grille(X,Y)
			;
			int x_g = evaluer_arbre(f->param1,ab,fleurs,grille);	
			int y_g = evaluer_arbre(f->param2,ab,fleurs,grille);
			return grille[x_g][y_g].element;
			break;
		case FCT_FLEUR :
			// fonction fleur(X,Y)
			;
			int x_f = evaluer_arbre(f->param1,ab,fleurs,grille);	
			int y_f = evaluer_arbre(f->param2,ab,fleurs,grille);
			if(grille[x_f][y_f].element==GRILLE_FLEUR){
				printf("JE SUIS UNE FLEUR !!!!!!");
				return grille[x_f][y_f].fl;
			}else
				return 0;
			break;
		case FCT_ENNEMIE : // a remodifier !!!!!!!!
			// fonction ennemie(X,Y)
			;
			int x_e = evaluer_arbre(f->param1,ab,fleurs,grille);	
			int y_e = evaluer_arbre(f->param2,ab,fleurs,grille);
			
			abeille * a = (abeille *)recherche_ennemie(grille[x_e][y_e].liste_abeille,ab->num_ruche);
			
			if(a == NULL)
				return 0;
			else
				return a->num;
			break;
		case FCT_ESTLIBRE :
			// fonction estLibre(id)
			;
			int id = evaluer_arbre(f->param1,ab,fleurs,grille);
			return fleurs[id]->estlibre;
			break;
		case FCT_NECTAR :
			// fonction nectar(id)
			;
			int id_n = evaluer_arbre(f->param1,ab,fleurs,grille);
			return fleurs[id_n]->nectar;
			break;
		case FCT_DISTANCE :
			// fonction distance(X1,Y1,X2,Y2)
			;
			int x1 = evaluer_arbre(f->param1,ab,fleurs,grille);
			int y1 = evaluer_arbre(f->param2,ab,fleurs,grille);
			int x2 = evaluer_arbre(f->param3,ab,fleurs,grille);
			int y2 = evaluer_arbre(f->param4,ab,fleurs,grille);
			int diff_x = fabs(x2-x1);
			int diff_y = fabs(y2-y1);
			return sqrt((diff_x*diff_x)+(diff_y*diff_y));
			break;
	}
}

int evaluer_variable(symbole * s, abeille * ab, fleur ** fleurs, case_t grille[NB_COL][NB_LIGNES]){
	//printf("TOTOOTOTOTOT\n");
		//printf("NOM SYMBOLE : %d \n",s->type);
	
	if(s->type==SYMBOLE_VARIABLE_USER){
		//printf("NOM SYMBOLE : %s \n",s->nom);
		return evaluer_arbre(s->valeur,ab,fleurs,grille);}
	else {
		if(strcmp(s->nom,"ENERGIE")==0)
			return ab->energie;
		if(strcmp(s->nom,"MAX_ENERGIE")==0)
			return ab->energiemax;
		if(strcmp(s->nom,"NECTAR")==0)
			return ab->nectar;
		if(strcmp(s->nom,"MAX_NECTAR")==0)
			return ab->nectarmax;
		if(strcmp(s->nom,"MEMX")==0)
			return ab->memx;
		if(strcmp(s->nom,"MEMY")==0)
			return ab->memy;
		if(strcmp(s->nom,"POSX")==0)
			return ab->posx;
		if(strcmp(s->nom,"POSY")==0)
			return ab->posy;
		if(strcmp(s->nom,"RUCHEX")==0)
			return ab->ruchex;
		if(strcmp(s->nom,"RUCHEY")==0)
			return ab->ruchey;
		if(strcmp(s->nom,"LARGEUR")==0)
			return NB_LIGNES;
		if(strcmp(s->nom,"HAUTEUR")==0)
			return NB_COL;
		
	}
	
}
